"""
"""
import unittest as ut
import sys
from pprint import pformat

import basicVdsTest as vdst
import vdsClient as vdsc
from vdsClient import BLANK_UUID
from storageConnectionTestUtils import eStorageType, disconnectFromStorage, connectToStorage, validateConnections, CONNECTIONS_OPTION_DEFAULT
from storageDomainTestUtils import eDomainClass, getDomainTargets, destroyDomainTargets
from confUtils import Validate
from subprocess import Popen
import time

class LvMetaDataCorrupt(vdst.BasicVDSTest):
    #For convenience. I didn't put it in the base class because I didn't want to commit.
    mycfg = property(lambda self: self.cfg[self.__class__.__name__])
    @classmethod
    def getConfigTemplate(cls):
        return {cls.__name__: {
                "VdsUri1" : {"default" : "http://server:54321"},
                "Connections" : {"default" : CONNECTIONS_OPTION_DEFAULT, "validator" : validateConnections},
                "DomainClass1" : {"default" : "data", "validator" : eDomainClass.parse},
                "Domain1" : {"default" : "GUID, GUID", "validator" : Validate.list},
                "StorageType1": {"default" : "nfs", "validator" : eStorageType.parse},
                "DomainClass2" : {"default" : "data", "validator" : eDomainClass.parse},
                "Domain2" : {"default" : "GUID, GUID", "validator" : Validate.list},
                "StorageType2": {"default" : "nfs", "validator" : eStorageType.parse},
                "HostID1" : {"default" : 7, "validator" : Validate.int},
                "Pool1Key" : {"default" : "NFSKEY"}
            }
        }

    def setUp(self):
        #Setup client
        self.client = vdsc.VDSClient()
        self.client.setURI(self.mycfg["VdsUri1"])

        #Make sure env is clean
        succeeded, resp = self.assertVdscOK(self.client.getConnectedStoragePoolsList())
        self.assertTrue(len(resp['poollist']) == 0, "VDSM is connected to a pool. Dirty env. Bailing out.")

        #Handle storage configuration
        connectToStorage(self.client, self.mycfg["Connections"])
        self.domainTarget1, self.domainTarget2 = getDomainTargets(self.client, self.mycfg["Connections"], [self.mycfg["Domain1"], self.mycfg["Domain2"]])

        #setup test variables
        self.sdUUID1 = self.client.newUUID()
        self.sdUUID2 = self.client.newUUID()
        self.spUUID = self.client.newUUID()

        #Create the tmp domains
        self.assertVdscOK(
            self.client.createStorageDomain(self.mycfg["StorageType1"], self.sdUUID1,
                "Storage Domain 1", self.domainTarget1, self.mycfg["DomainClass1"]
            )
        )

        self.assertVdscOK(
            self.client.createStorageDomain(self.mycfg["StorageType2"], self.sdUUID2,
                "Storage Domain 2", self.domainTarget2, self.mycfg["DomainClass2"]
            )
        )

        #Create tmp pool
        self.assertVdscOK(
            self.client.createStoragePool(self.spUUID, "Swimming Pool", self.sdUUID1, [self.sdUUID1, self.sdUUID2], 1)
            )

        self.assertVdscOK(
            self.client.connectStoragePool(self.spUUID, self.mycfg["HostID1"], self.mycfg["Pool1Key"])
            )

        taskid = self.assertVdscOK(self.client.spmStart(self.spUUID, -1, -1, -1, False))[1]['uuid']
        self.assertVdscTaskOK(self.client, taskid)

        self.assertVdscOK(
            self.client.activateStorageDomain(self.sdUUID1, self.spUUID)
        )

        self.assertVdscOK(
            self.client.activateStorageDomain(self.sdUUID2, self.spUUID)
        )

    def test(self):
        self.imgUUID1 = vdsc.VDSClient.newUUID()
        self.imgUUID2 = vdsc.VDSClient.newUUID()
        self.volUUID1 = vdsc.VDSClient.newUUID()
        self.volUUID2 = vdsc.VDSClient.newUUID()
        self.vmUUID = vdsc.VDSClient.newUUID()

        volsize = 5120*2

        taskID = self.assertVdscOK(
            self.client.createVolume(self.sdUUID1, self.spUUID, self.imgUUID1, volsize,
            vdsc.COW_FORMAT, vdsc.SPARSE_VOL, "DATA", self.volUUID1, "Volly The Volume", blocked=False)
        )[1]['uuid']
        self.assertVdscTaskOK(self.client, taskID)

        self.assertVdscOK(
            self.client.copyImage(self.sdUUID1, self.spUUID, self.vmUUID,
                self.imgUUID1, self.volUUID1, self.imgUUID2, self.volUUID2, "DasdAS", self.sdUUID1, vdsc.SHARED_VOL,
                vdsc.COW_FORMAT, vdsc.SPARSE_VOL)
            )
        tasks = []
        volUUIDs = []
        imgUUIDs = []
        dupImgUUID = vdsc.VDSClient.newUUID()
        numOfVols = 35
        for i in range(numOfVols):
            print "%d/%d" % (i + 1, numOfVols)
            volUUIDs.append(vdsc.VDSClient.newUUID())
            #imgUUIDs.append(dupImgUUID)
            imgUUIDs.append(vdsc.VDSClient.newUUID())
            taskID = self.assertVdscOK(
                self.client.createVolume(self.sdUUID1, self.spUUID, imgUUIDs[i], volsize,
                vdsc.COW_FORMAT, vdsc.SPARSE_VOL, "DATA", volUUIDs[i], "Volly The Volume",
                self.imgUUID2, self.volUUID2, blocked=False)
            )[1]['uuid']
            tasks.append(taskID)

        i = 0
        deleteTasks = []
        for task in tasks:
            print "Waiting for task %s" % task
            self.assertVdscTaskOK(self.client, task)

            validate = {'apparentsize' : int,
                    'children' : [],
                    'ctime' : int,
                    'description': 'Volly The Volume',
                     'disktype': 'DATA',
                     'domain': self.sdUUID1,
                     'format': 'COW',
                     'image':'',
                     'legality': 'LEGAL',
                     'mtime': int,
                     'parent': self.volUUID2,
                     'pool': self.spUUID,
                     'size': volsize,
                     'status': 'OK',
                     'truesize': int,
                     'type': 'SPARSE',
                     'uuid':'',
                     'voltype': 'LEAF'}

            print "Validating LV '%s' (%d/%d)" % (volUUIDs[i], i + 1, len(volUUIDs))
            validate['image'] = imgUUIDs[i]
            validate['uuid'] = volUUIDs[i]
            info = self.assertVdscOK(
            self.client.getVolumeInfo(self.sdUUID1, self.spUUID, imgUUIDs[i], volUUIDs[i])
            )[1]['info']
            for key, value in validate.iteritems():
                if callable(value):
                    try:
                        value(info[key])
                    except:
                        self.assertFail("Key '%s' didn't validate value '%s'" % (key, value))
                else:
                    self.assertEquals(value, info[key])

            taskUUID = self.assertVdscOK(
                self.client.deleteVolume(self.sdUUID1, self.spUUID, imgUUIDs[i], [volUUIDs[i]], blocked = False)
                )[1]['uuid']

            deleteTasks.append(taskUUID)
            i += 1

        for task in deleteTasks:
            print "Waiting for task %s" % task
            self.assertVdscTaskOK(self.client, task)

    def tearDown(self):
        print "Press key to clean"
        sys.stdin.read(1)
        print "Cleaning..."
        self.assertVdscOK(
            self.client.deactivateStorageDomain(self.sdUUID2, self.spUUID, self.sdUUID1, -1)
        )
        self.assertVdscOK(
            self.client.deactivateStorageDomain(self.sdUUID1, self.spUUID, BLANK_UUID, -1)
        )

        #Destroy pool
        self.assertVdscOK(self.client.destroyStoragePool(self.spUUID, self.mycfg["HostID1"], self.mycfg["Pool1Key"]))

        #format domain
        self.assertVdscOK(self.client.formatStorageDomain(self.sdUUID1))
        self.assertVdscOK(self.client.formatStorageDomain(self.sdUUID2))

        #disconnect
        destroyDomainTargets(self.client, [self.domainTarget1, self.domainTarget2])
        disconnectFromStorage(self.client, self.mycfg["Connections"])

def suite():
    tests = {
        LvMetaDataCorrupt: ["test"]
    }

    resSuite = ut.TestSuite()
    for testcase, methods in tests.iteritems():
        resSuite.addTests(map(testcase, methods))

    return resSuite

validateConfig = lambda cfg : vdst.validateSuiteConfig(suite(), cfg)

